package pkg.andru.animation;

import pkg.andru.animation.Sprite.SpriteDrawState;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.util.Log;

/**
 * the sprite class, the smallest draw unit
 * 
 * @author idiottiger
 * 
 */
public class Sprite implements IDrawable<SpriteDrawState> {

    static final String TAG = "Sprite";

    /** the sprite id, integer, unique id **/
    private int id;

    /** the sprite name alias, can be null **/
    private String name;

    /** the sprite bitmap, requied **/
    private Bitmap bitmap;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Bitmap getBitmap() {
        return bitmap;
    }

    public void setBitmap(Bitmap bitmap) {
        this.bitmap = bitmap;
    }

    public void release() {
        bitmap.recycle();
    }

    boolean isBitmapOK() {
        return bitmap != null && !bitmap.isRecycled();
    }

    @Override
    public String toString() {
        return "Sprite [id=" + id + ", name=" + name + ", isBitmapOK()=" + isBitmapOK() + "]";
    }

    public static class SpriteDrawState implements IDrawState {

        Matrix matrix;

        Paint paint;

        final float mX, mY;
        final float alpha;

        RotateState rotateState;
        ScaleState scaleState;

        public SpriteDrawState(float x, float y, float al) {
            mX = x;
            mY = y;
            alpha = al;
            matrix = new Matrix();
            matrix.setTranslate(x, y);

            paint = new Paint();
            paint.setAlpha((int) (al * 255));
        }

        /**
         * set position
         * 
         * @param x
         * @param y
         */
        public void updatePosition(float x, float y) {
            matrix.reset();
            matrix.setTranslate(mX + x, mY + y);
            if (rotateState != null) {
                rotateState.updateMatrix(matrix);
            }
            if (scaleState != null) {
                scaleState.updateMatrix(matrix);
            }
        }

        /**
         * set rotate
         * 
         * @param x
         * @param y
         * @param degrees
         */
        public void setRotate(float x, float y, float degrees) {
            rotateState = new RotateState();
            rotateState.init(x, y, degrees);
        }

        /**
         * set the scale
         * 
         * @param x
         * @param y
         * @param scaleX
         * @param scaleY
         */
        public void setScale(float x, float y, float scaleX, float scaleY) {
            scaleState = new ScaleState();
            scaleState.init(x, y, scaleX, scaleY);
        }

        /**
         * set the alpha
         * 
         * @param alpha
         */
        public void updateAlpha(float al) {
            int value = (int) (alpha * al * 255);
            paint.setAlpha(value);
        }

        /**
         * reset drawstate
         */
        public void reset() {
            matrix.reset();
            paint.reset();
        }

        @Override
        public String toString() {
            return "SpriteDrawState [matrix=" + matrix + ", paint=" + paint + ", mX=" + mX + ", mY=" + mY + ", alpha=" + alpha + "]";
        }

        class RotateState implements IState {
            float mx, my, mdegrees;

            public void init(float x, float y, float degrees) {
                mx = x;
                my = y;
                mdegrees = degrees;
            }

            public void updateMatrix(Matrix matrix) {
                matrix.postRotate(mdegrees, mx, my);
            }
        }

        class ScaleState implements IState {
            float mx, my, msx, msy;

            public void init(float x, float y, float sx, float sy) {
                mx = x;
                my = y;
                msx = sx;
                msy = sy;
            }

            public void updateMatrix(Matrix matrix) {
                matrix.postScale(msx, msy, mx, my);
            }
        }

        static interface IState {
            public void updateMatrix(Matrix matrix);
        }
    }

    @Override
    public void onDraw(Canvas canvas, SpriteDrawState state) {
        if (isBitmapOK()) {
            Log.i(TAG, "matrix:" + state.matrix.toShortString());
            canvas.drawBitmap(bitmap, state.matrix, state.paint);
        }
    }
}
